🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / docs / en / developer / navigation-and-deep-links.md
Displaying Raw • View rendered • Download
docs/en/developer/navigation-and-deep-links.md bd2863243bab6eb213401d949839a2bc74dde7e2 (bd286324) Text, 6.88 KB
---
title: Navigation & Deep Links
parent: Developer Guide
nav_order: 4
last_updated: 2026-07-08
aliases:
Tff7b72- deeplinks
Tff7b72- navigation-3
Tc9d1d9 - routes
Tc9d1d9---
Tc9d1d9# Navigation & Deep Links
The app uses **Navigation 3** with typed, serializable routes and centralized deep link resolution.
Tc9d1d9## Route Architecture
All routes are defined in Ta5d6ff`core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/Routes.kt`.
Tc9d1d9### Route Hierarchy
Ta5d6ff```Ta5d6ffkotlin
Tff7b72interface T56d364Route Tb4b4b4: Te6edf3NavKey T8b949e// All routes implement NavKey
Tff7b72interface T56d364Graph Tb4b4b4: Te6edf3Route T8b949e// Graph roots for navigation hierarchies
Tf0883e@Serializable
Tff7b72sealed Tff7b72interface T56d364SettingsRoute Tb4b4b4: Te6edf3Route Tb4b4b4{
Tf0883e@Serializable Tff7b72data Tff7b72class T56d364SettingsTb4b4b4(Tff7b72val Te6edf3destNumTb4b4b4: Tffa657Int? Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4: Te6edf3SettingsRouteTb4b4b4, Te6edf3Graph
Tf0883e@Serializable Tff7b72data Tff7b72object T56d364DeviceConfiguration Tb4b4b4: Te6edf3SettingsRoute
Tf0883e@Serializable Tff7b72data Tff7b72object T56d364HelpDocs Tb4b4b4: Te6edf3SettingsRoute
Tf0883e@Serializable Tff7b72data Tff7b72class T56d364HelpDocPageTb4b4b4(Tff7b72val Te6edf3pageIdTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4: Te6edf3SettingsRoute
T8b949e// ...
Tb4b4b4}
Ta5d6ff```
Tc9d1d9### Conventions
Tff7b72- Routes are Ta5d6ff`@Serializable` for state restoration
Tff7b72- Use Ta5d6ff`data object` for routes without parameters
Tff7b72- Use Ta5d6ff`data class` for parameterized routes
Tff7b72- Group related routes under a Ta5d6ff`sealed interface`
Tff7b72- Graph entry points implement both the route interface and Ta5d6ff`Graph`
Tc9d1d9## Deep Link Router
Ta5d6ff`DeepLinkRouter` in Ta5d6ff`core/navigation` maps URI deep links to typed backstack lists.
Tc9d1d9### URI Format
Both forms resolve through the same Ta5d6ff`DeepLinkRouter`, so any path below works with either scheme:
Ta5d6ff```Ta5d6fftext
meshtastic://meshtastic/{path}
https://meshtastic.org/{path} # App Link, android:autoVerify — also opens in-app on a real device/adb
Ta5d6ff```
Ta5d6ff`adb shell am start -a android.intent.action.VIEW -d "meshtastic://meshtastic/{path}"` is the fastest way to
trigger any route below from a shell or automation script without touching the UI.
For the Ta5d6ff`https` form to open in-app, each top-level path segment must also be declared as an
Ta5d6ff`android:pathPrefix` in the Ta5d6ff`android:autoVerify` intent-filter in Ta5d6ff`androidApp/src/main/AndroidManifest.xml` —
otherwise the link opens in the browser. Adding a new top-level route therefore takes three steps: add the
segment to Ta5d6ff`DeepLinkRouter.topLevelPathSegments` (the router refuses to dispatch segments outside that set),
add its Ta5d6ff`when` branch in Ta5d6ff`DeepLinkRouter.route()`, and add the matching Ta5d6ff`pathPrefix` to the manifest.
Ta5d6ff`DeepLinkManifestConsistencyTest` (androidApp unit tests) checks the manifest against the set, so a missing
manifest entry fails CI.
**Source of truth:** the always-current list of top-level segments is Ta5d6ff`topLevelPathSegments` in
[Ta5d6ff`DeepLinkRouter`](https://github.com/meshtastic/Meshtastic-Android/blob/main/core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/DeepLinkRouter.kt)
— sub-paths live in the Ta5d6ff`route()` Ta5d6ff`when` block plus its helper maps (Ta5d6ff`settingsSubRoutes`, Ta5d6ff`nodeDetailSubRoutes`);
the class-level KDoc is illustrative, not exhaustive. It also exists as executable spec in
[Ta5d6ff`DeepLinkRouterTest.kt`](https://github.com/meshtastic/Meshtastic-Android/blob/main/core/navigation/src/commonTest/kotlin/org/meshtastic/core/navigation/DeepLinkRouterTest.kt).
The table below is a snapshot for quick reference — check those two files if it looks out of date.
Tc9d1d9### Supported Deep Links
| URI Path | Route | Notes |
|----------|-------|-------|
| Ta5d6ff`/connections` | Ta5d6ff`ConnectionsRoute.Connections(null)` | Connections screen |
| Ta5d6ff`/connections?address={prefixedAddress}` | Ta5d6ff`ConnectionsRoute.Connections(address)` | Auto-connects to a device without manual selection — the address uses the app's internal transport-prefixed format: Ta5d6ff`t192.168.1.1:4403` (TCP), Ta5d6ff`xAA:BB:CC:DD:EE:FF` (BLE), Ta5d6ff`s/dev/ttyUSB0` (serial). Intended for scripts/AI tooling driving the app. |
| Ta5d6ff`/connections?address=n` | Ta5d6ff`ConnectionsRoute.Connections("n")` | Disconnects the current device instead of connecting (Ta5d6ff`n` = the internal "no device selected" sentinel). |
| Ta5d6ff`/wifi-provision` | Ta5d6ff`WifiProvisionRoute.WifiProvision(null)` | WiFi provisioning screen |
| Ta5d6ff`/wifi-provision?address={mac}` | Ta5d6ff`WifiProvisionRoute.WifiProvision(mac)` | Provisioning targeting a specific device MAC |
| Ta5d6ff`/settings` | Ta5d6ff`SettingsRoute.Settings(null)` | Settings root |
| Ta5d6ff`/settings/helpDocs` | Ta5d6ff`SettingsRoute.HelpDocs` | Docs browser |
| Ta5d6ff`/settings/helpDocs/{pageId}` | Ta5d6ff`SettingsRoute.HelpDocPage(pageId)` | Specific doc page |
| Ta5d6ff`/settings/help-docs` | Ta5d6ff`SettingsRoute.HelpDocs` | Compatibility alias |
| Ta5d6ff`/discovery` | Ta5d6ff`DiscoveryRoute.DiscoveryGraph` | Local Mesh Discovery entry point |
| Ta5d6ff`/settings/local-mesh-discovery/session/{sessionId}` | Ta5d6ff`DiscoveryRoute.DiscoverySummary(sessionId)` | Discovery session result |
| Ta5d6ff`/nodes` | Ta5d6ff`NodesRoute.Nodes` | Node list |
| Ta5d6ff`/nodes/{destNum}` | Ta5d6ff`NodesRoute.NodeDetail(destNum)` | Node detail |
| Ta5d6ff`/nodes/{destNum}/{metric}` | e.g. Ta5d6ff`NodeDetailRoute.DeviceMetrics(destNum)` | Specific node metric tab (Ta5d6ff`device-metrics`, Ta5d6ff`signal`, Ta5d6ff`power`, Ta5d6ff`traceroute`, Ta5d6ff`pax`, Ta5d6ff`neighbors`, ...) |
| Ta5d6ff`/messages` | Ta5d6ff`ContactsRoute.Contacts` | Conversation list |
| Ta5d6ff`/messages/{contactKey}` | Ta5d6ff`ContactsRoute.Messages(contactKey)` | Specific conversation |
| Ta5d6ff`/share?message={text}` | Ta5d6ff`ContactsRoute.Share(message)` | Share-to-contact composer |
| Ta5d6ff`/quickchat` | Ta5d6ff`ContactsRoute.QuickChat` | Quick chat picker |
| Ta5d6ff`/map` | Ta5d6ff`MapRoute.Map(null)` | Map view |
| Ta5d6ff`/map/{waypointId}` | Ta5d6ff`MapRoute.Map(waypointId)` | Map centered on a waypoint |
| Ta5d6ff`/channels` | Ta5d6ff`ChannelsRoute.Channels` | Channel list |
| Ta5d6ff`/firmware` | Ta5d6ff`FirmwareRoute.FirmwareGraph` | Firmware screen |
| Ta5d6ff`/firmware/update` | Ta5d6ff`FirmwareRoute.FirmwareUpdate` | Firmware update flow |
Tc9d1d9### Backstack Synthesis
Deep links synthesize a full backstack, not just the target screen:
Ta5d6ff```Ta5d6ffkotlin
T8b949e// /settings/helpDocs/messages-and-channels produces:
Te6edf3listOfTb4b4b4(
Te6edf3SettingsRouteTb4b4b4.Te6edf3SettingsTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4,
Te6edf3SettingsRouteTb4b4b4.Te6edf3HelpDocsTb4b4b4,
Te6edf3SettingsRouteTb4b4b4.Te6edf3HelpDocPageTb4b4b4(Ta5d6ff"Ta5d6ffmessages-and-channelsTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Ta5d6ff```
This ensures the user can navigate "up" correctly.
Tc9d1d9## Adding a Deep Link
Tff7b721. Define the typed route in Ta5d6ff`Routes.kt`.
Tff7b722. Add the mapping in Ta5d6ff`DeepLinkRouter.settingsSubRoutes` (or equivalent for other graphs).
Tff7b723. Add a test in Ta5d6ff`DeepLinkRouterTest.kt`.
Tff7b724. Register the navigation entry in the appropriate feature module.
Tff7b725. Update the KDoc list on Ta5d6ff`DeepLinkRouter.route()` and the table above — they're the two places tooling/agents look to discover what deep links exist.
Tc9d1d9## Navigation Entry Registration
Each feature module provides entries via an extension function:
Ta5d6ff```Ta5d6ffkotlin
Tff7b72fun Td2a8ffEntryProviderScopeTff7b72<Te6edf3NavKeyTff7b72>Tb4b4b4.Te6edf3docsEntriesTb4b4b4(Te6edf3backStackTb4b4b4: Te6edf3NavBackStackTff7b72<Te6edf3NavKeyTff7b72>Tb4b4b4) Tb4b4b4{
Te6edf3entryTff7b72<Te6edf3SettingsRouteTb4b4b4.Te6edf3HelpDocsTff7b72> Tb4b4b4{ Te6edf3DocsBrowserScreenTb4b4b4(Te6edf3backStackTb4b4b4) Tb4b4b4}
Te6edf3entryTff7b72<Te6edf3SettingsRouteTb4b4b4.Te6edf3HelpDocPageTff7b72> Tb4b4b4{ Te6edf3route Tff7b72-Tff7b72> Te6edf3DocsPageRouteScreenTb4b4b4(Te6edf3routeTb4b4b4.Te6edf3pageIdTb4b4b4, Te6edf3backStackTb4b4b4) Tb4b4b4}
Tb4b4b4}
Ta5d6ff```
These are called from the settings navigation composition.
Tc9d1d9## Testing
Deep link routing is tested in:
Ta5d6ff```
core/navigation/src/commonTest/kotlin/org/meshtastic/core/navigation/DeepLinkRouterTest.kt
```
---
Served by rngit 1.5.0 - Generated in 0.11s